package com.gitee.wsl.prop

import kotlin.reflect.KClass

/**
 * Class to hold data in [io.noties.markwon.base.RenderProps]. Represents a certain *property*.
 *
 * @param <T> represents the type that this instance holds
 * @see .of
 * @see .of
 * @since 3.0.0
</T> */
open class Prop<T> constructor( val name: String,val defaultValue:T?=null) {
    fun name(): String {
        return name
    }

    operator fun get(props: PropContainer): T? {
        return props.get(this)?:defaultValue
    }

    operator fun get(props: PropContainer, defValue: T): T {
        return props.get(this, defValue)
    }

    fun require(props: PropContainer): T {
        return get(props) ?: throw NullPointerException(name)
    }

    operator fun set(props: PropContainer, value: T?) {
        props.set(this, value)
    }

    fun clear(props: PropContainer) {
        props.clear(this)
    }

    /*override fun equals(o: Any?): Boolean {
        if (this === o) return true
        if (o == null || javaClass != o.javaClass) return false
        val prop = o as Prop<*>
        return name == prop.name
    }*/

    override fun hashCode(): Int {
        return name.hashCode()
    }

    override fun toString(): String {
        return "Prop{" +
                "name='" + name + '\'' +
                "defaultValue='" + defaultValue + '\'' +
                '}'
    }

    open fun valueOf(value: String): T? {
       return null
    }

    companion object {

        fun <T : Any> of(type: KClass<T>, name: String): Prop<T> {
            return Prop(name)
        }

        fun <T> of(name: String): Prop<T> {
            return Prop(name)
        }
    }
}

class StringProp (name: String,defaultValue:String?=null): Prop<String>(name,defaultValue){

    override fun valueOf(value: String): String? {
        return value
    }

    companion object{
        fun of(name: String): StringProp{
            return StringProp(name)
        }

        fun of(name: String,defaultValue:String?=null): StringProp{
            return StringProp(name,defaultValue)
        }
    }
}

class BooleanProp(name: String,defaultValue:Boolean?=null): Prop<Boolean>(name,defaultValue){
    override fun valueOf(value: String): Boolean? {
        return value.toBoolean()
    }

    companion object{
        fun of(name: String): BooleanProp{
            return BooleanProp(name)
        }

        fun of(name: String,defaultValue:Boolean?=null): BooleanProp{
            return BooleanProp(name,defaultValue)
        }

    }
}

class IntProp(name: String,defaultValue:Int?=null): Prop<Int>(name,defaultValue){
    override fun valueOf(value: String): Int? {
        return value.toIntOrNull()
    }

    companion object{
        fun of(name: String): IntProp{
            return IntProp(name)
        }

        fun of(name: String,defaultValue:Int?=null): IntProp{
            return IntProp(name,defaultValue)
        }
    }
}

class FloatProp(name: String,defaultValue:Float?=null): Prop<Float>(name,defaultValue){
    override fun valueOf(value: String): Float? {
        return value.toFloatOrNull()
    }

    companion object{
        fun of(name: String): FloatProp{
            return FloatProp(name)
        }

        fun of(name: String,defaultValue:Float?=null): FloatProp{
            return FloatProp(name,defaultValue)
        }
    }
}

class DoubleProp(name: String,defaultValue:Double?=null): Prop<Double>(name,defaultValue){
    override fun valueOf(value: String): Double? {
        return value.toDoubleOrNull()
    }

    companion object{
        fun of(name: String): DoubleProp{
            return DoubleProp(name)
        }

        fun of(name: String,defaultValue:Double?=null): DoubleProp{
            return DoubleProp(name,defaultValue)
        }
    }
}